package cn.itcast.service.cargo.impl;

import cn.itcast.dao.cargo.*;
import cn.itcast.domain.cargo.*;
import cn.itcast.service.cargo.ExportService;
import cn.itcast.vo.ExportProductResult;
import cn.itcast.vo.ExportProductVo;
import cn.itcast.vo.ExportResult;
import cn.itcast.vo.ExportVo;
import com.alibaba.dubbo.config.annotation.Service;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.cxf.jaxrs.client.WebClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

/**
 * 报运单service接口实现类
 */
@Service
public class ExportServiceImpl implements ExportService {


	@Autowired
	private ExportDao exportDao;  //报运单dao

	@Autowired
	private ExportProductDao exportProductDao ;//报运单商品dao

	@Autowired
	private ExtEproductDao extEproductDao ;//报运单附件dao

	@Autowired
	private ContractDao contractDao; //合同dao

	@Autowired
	private ContractProductDao contractProductDao; // 合同货物dao

	@Autowired
	private ExtCproductDao extCproductDao; //合同附件dao

	//根据id查询
	public Export findById(String id) {
		return exportDao.selectByPrimaryKey(id);
	}

	/**
	 * 新增报运单:
	 *  参数Export对象（报运单对象）
	 *      i.常规属性（页面填写的内容）
	 *      ii.所有勾选的合同id（contractIds）,多个id间通过“，“隔开
	 * 业务代码编写
	 *  涉及到6个表操作
	 *  三个操作：
	 *      1.根据购销合同数据保存报运单数据
	 *      2.根据购销合同货物保存报运单商品数据
	 *      3.根据购销合同附件保存报运单附件数据
	 */
	public void save(Export export) {
	//i.根据购销合同数据保存报运单数据（包含了购销合同的id）
		//1、获取合同id
		int proNum = 0; //货物数
		int extNum = 0; //附件数
		String [] cids = export.getContractIds().split(","); //购销合同id
		String customerContract = "";
		for (String contractId : cids) {
			//2、根据合同id查询购销合同
			Contract contract = contractDao.selectByPrimaryKey(contractId);
			//3、拼接合同号的字符串(合同号间通过“ ”)，修改合同状态（state=2）
			customerContract += contract.getContractNo()+" ";
			contract.setState(2);
			contractDao.updateByPrimaryKeySelective(contract);
		}
		//4、报运单对象设置合同号，设置id
		export.setCustomerContract(customerContract);
		export.setId(UUID.randomUUID().toString());
	//ii.根据购销合同货物保存报运单商品数据（包含了购销合同的id）
		//1、根据勾选的购销合同id查询所有的合同货物 （货物表中有一个字段：contractId表示货物的购下合同）
		ContractProductExample cpe = new ContractProductExample();
		ContractProductExample.Criteria cc = cpe.createCriteria();
		cc.andContractIdIn(Arrays.asList(cids)) ;//参数是多个购销合同
		List<ContractProduct> cps = contractProductDao.selectByExample(cpe);
		//2、循环所有合同货物
		for (ContractProduct cp : cps) { //货物
			//3、通过货物构造商品
			ExportProduct ep = new ExportProduct();//商品
			//4、设置商品属性
			BeanUtils.copyProperties(cp,ep); //将cp中同名属性的值。赋值到ep中
			//5、设置商品的id
			ep.setId(UUID.randomUUID().toString());
			//6、设置商品的外键
			ep.setExportId(export.getId());
			//7、保存商品
			exportProductDao.insertSelective(ep);

	//iii.根据购合同附件，产生报运单附件数据
			//1、根据货物id，查询货物下的所有附件(附件中一个contractProductId表示获取id)
			ExtCproductExample ece = new ExtCproductExample();
			ExtCproductExample.Criteria ec = ece.createCriteria();
			ec.andContractProductIdEqualTo(cp.getId());
			List<ExtCproduct> ecps = extCproductDao.selectByExample(ece);
			//2、循环所有附件
			for (ExtCproduct ecp : ecps) {
				//3、根据货物附件构造报运单附件
				ExtEproduct eep = new ExtEproduct();//报运单附件
				//4、设置报运单附件的属性
				BeanUtils.copyProperties(ecp,eep);
				//5、设置报运单附件的id
				eep.setId(UUID.randomUUID().toString());
				//6、设置报运单附件商品id
				eep.setExportProductId(ep.getId());
				//7、设置报运单附件的报运单id
				eep.setExportId(export.getId());
				//8、保存附件
				extEproductDao.insertSelective(eep);
			}
			extNum += ecps.size();
		}
		proNum = cps.size(); //设置货物数量
		export.setProNum(proNum); //货物数
		export.setExtNum(extNum); //附件数
		export.setState(0); //草稿状态
		exportDao.insertSelective(export);
	}

	/**
	 * 更新
	 *  参数；export对象
	 *      * 报运单主体数据（更新即可）
	 *      * 此报运单下更新的所有商品（exportProducts）
	 */
	public void update(Export export) {
		//1.更新报运单
		exportDao.updateByPrimaryKeySelective(export);
		//2.循环报运单下更新的所有商品，更新每个商品
		if(export.getExportProducts() != null) {
			for (ExportProduct ep : export.getExportProducts()) {
				exportProductDao.updateByPrimaryKeySelective(ep);
			}
		}
	}

	/**
	 * 删除
	 */
	public void delete(String id) {
		exportDao.deleteByPrimaryKey(id);
	}

	//分页
	public PageInfo findAll(ExportExample example, int page, int size) {
		PageHelper.startPage(page,size);
		List<Export> list = exportDao.selectByExample(example);
		return new PageInfo(list);
	}

	/**
	 * 海关保运
	 *  参数：报运单ID
	 */
	public void exportE(String id) {
		//1.根据id查询报运单
		Export export = exportDao.selectByPrimaryKey(id);
		//2.根据报运单id查询报运单的所有商品
		ExportProductExample example = new ExportProductExample();
		ExportProductExample.Criteria criteria = example.createCriteria();
		//条件：商品中有一个字段ExportID（商品所属的报运单id）
		criteria.andExportIdEqualTo(id);
		List<ExportProduct> eps = exportProductDao.selectByExample(example);
		//3.将Export对象转化为海关保运的ExportVo对象
		ExportVo evo = new ExportVo();
		BeanUtils.copyProperties(export,evo);
		//设置报运单id
		evo.setExportId(export.getId());
		//4.将ExportProduct对象转化为海关保运的ExportProduct对象
		List<ExportProductVo> epvos = new ArrayList<>();
		for (ExportProduct ep : eps) {
			ExportProductVo epvo = new ExportProductVo();
			BeanUtils.copyProperties(ep,epvo);
			epvo.setExportProductId(ep.getId());
			epvos.add(epvo);
		}
		evo.setProducts(epvos); //报运单vo对象中包含了所有的商品
		//5.通过WebClient工具类发送数据
		WebClient wc = WebClient.create("http://localhost:9001/ws/export/ep");
		/**
		 * 参数
		 *  传递的数据对象，
		 *  响应的数据类型，
		 * 返回值
		 *  响应数据
		 */
		Integer res = wc.post(evo, Integer.class);
		//6.更新数据库状态（2）
		if(res == 0) {
			export.setState(2);
			exportDao.updateByPrimaryKeySelective(export);
		}
	}

	//查询所有的报运单
	public List<Export> findAll(ExportExample example) {
		return exportDao.selectByExample(example);
	}

	/**
	 * 更新保运结果
	 *  ExportResult : 海关的保运结果
	 *          exportId： 报运单id
	 *          state：海关的保运状态
	 *          remark：保运结果的中文说明
	 *          products ：
	 *              报运单的所有商品信息
	 *                  exportProductId：商品id
	 *                  tax：商品关说
	 */
	public void updateE(ExportResult result) {
		//1.查询报运单
		Export export = exportDao.selectByPrimaryKey(result.getExportId());
		//2.更新报运单数据
		export.setState(result.getState());
		export.setRemark(result.getRemark());
		exportDao.updateByPrimaryKeySelective(export);
		//3.循环报运单所有商品
		for (ExportProductResult product : result.getProducts()) {
			ExportProduct exportProduct = exportProductDao.selectByPrimaryKey(product.getExportProductId());
			exportProduct.setTax(product.getTax());
			//4.更新报运单税
			exportProductDao.updateByPrimaryKeySelective(exportProduct);
		}
	}
}
